package common

import (
	"fmt"
	"strings"

	"github.com/go-ini/ini"
)

type ConfigFunc func(key, value any) bool

type Config struct {
	value *OrderedMap
	cn    map[string]string
	cfg   *ini.File
}

func (c *Config) initCN() {
	c.cn["Difficulty"] = "难度 1、2、3整数，简单、普通、困难，影响怪物血量之类的数值"
	c.cn["DayTimeSpeedRate"] = "白天流逝速度 0.1~5之间"
	c.cn["NightTimeSpeedRate"] = "夜晚流逝速度 0.1~5之间"
	c.cn["ExpRate"] = "经验倍率 0.1~3之间"
	c.cn["PalCaptureRate"] = "帕鲁捕捉概率 0.5~2之间"
	c.cn["PalSpawnNumRate"] = "帕鲁出现倍率 0.5~3之间，比如2，boss也会出现2个"
	c.cn["PalDamageRateAttack"] = "帕鲁攻击伤害倍率 0.1~5之间"
	c.cn["PalDamageRateDefense"] = "帕鲁承受伤害倍率 0.1~5之间，越低越抗揍"
	c.cn["PlayerDamageRateAttack"] = "玩家攻击伤害倍率 0.1~5之间，越高输出越高"
	c.cn["PlayerDamageRateDefense"] = "玩家承受伤害倍率 0.1~5之间，越低越抗揍"
	c.cn["PlayerStomachDecreaceRate"] = "玩家饱食度降低倍率 0.1~5之间，越低越耐饿"
	c.cn["PlayerStaminaDecreaceRate"] = "玩家耐力降低倍率 0.1~5之间，数值越低 耐力降低越慢"
	c.cn["PlayerAutoHPRegeneRate"] = "玩家生命值恢复倍率 0.1~5之间，数值越高自动回复越快"
	c.cn["PlayerAutoHpRegeneRateInSleep"] = "玩家睡眠生命值恢复倍率 0.1~5之间，数值越高睡觉回血越快"
	c.cn["PalStomachDecreaceRate"] = "帕鲁饱食度降低倍率 0.1~5之间，越低越耐饿"
	c.cn["PalStaminaDecreaceRate"] = "帕鲁耐力降低倍率0.1~5之间，数值越低 耐力降低越慢 0.1~5之间，数值越低 耐力降低越慢"
	c.cn["PalAutoHPRegeneRate"] = "帕鲁生命值恢复倍率0.1~5之间，数值越高自动回复越快 0.1~5之间，数值越高自动回复越快"
	c.cn["PalAutoHpRegeneRateInSleep"] = "帕鲁睡眠时生命值恢复倍率0.1~5之间，数值越高自动回复越快 0.1~5之间，数值越高自动回复越快"
	c.cn["BuildObjectDamageRate"] = "对建筑物伤害倍率0.5~3之间，建议调低，调高了会不小心拆掉自己的房子 0.5~3之间，建议调低，调高了会不小心拆掉自己的房子"
	c.cn["BuildObjectDeteriorationDamageRate"] = "建筑物劣化速度倍率0~10之间，建议调0，建筑不会自己损坏 0~10之间，建议调0，建筑不会自己损坏"
	c.cn["CollectionDropRate"] = "可采集物品掉落倍率0.5~3之间，调高了树木和矿物获取一次性获取更多 0.5~3之间，调高了树木和矿物获取一次性获取更多"
	c.cn["CollectionObjectHpRate"] = "可采集物品生命值倍率0.5~3之间，调低可以加快挖矿速度 0.5~3之间，调低可以加快挖矿速度"
	c.cn["CollectionObjectRespawnSpeedRate"] = "可采集物品刷新间隔，0.5~3之间，调低可加快野矿刷新速度"
	c.cn["EnemyDropItemRate"] = "道具掉落量倍率，0.5~3之间，如果调到3，比如击杀掉黑市商人，默认掉一把钥匙，会变成三把，金币掉落量也会三倍"
	c.cn["DeathPenalty"] = "死亡惩罚：None不掉落，Item只掉物品不掉装备，ItemAndEquipment掉物品和装备，All全都掉，建议None提高游戏舒适性，不然每次死都得跑尸"
	c.cn["bEnablePlayerToPlayerDamage"] = "启用玩家对玩家伤害功能，True或者False"
	c.cn["bEnableFriendlyFire"] = "启用火焰伤害（False的时候，踩到自家篝火会着火掉血，改True就好）"
	c.cn["bEnableInvaderEnemy"] = "是会发生袭击事件（野怪入侵基地），True是开启，改为False关闭"
	c.cn["bActiveUNKO"] = "UNKO应该是日语指代的粪便，个人理解是否开启帕鲁粪便吧好像，建议False不动"
	c.cn["bEnableAimAssistPad"] = "启用平板辅助瞄准True是开启，False关闭"
	c.cn["bEnableAimAssistKeyboard"] = "启用键盘辅助瞄准True是开启，False关闭"
	c.cn["DropItemMaxNum"] = "世界内掉落物品数量上限，指代野外可以捡到的东西数量上限，数量多了吃服务器性能。默认是3000，上限5000，看自己需要修改"
	c.cn["DropItemMaxNum_UNKO"] = "帕鲁屎掉落上限？不确定。可以不管"
	c.cn["BaseCampMaxNum"] = "大本营最大数，128默认即可，多人游戏时如果有多个工会，会限制所有工会加起来的营地上限"
	c.cn["BaseCampWorkerMaxNum"] = "可分派至据点工作的帕鲁数量上限，1~20之间整数。默认15"
	c.cn["DropItemAliveMaxHours"] = "掉落物品存在最大时长，默认1，上限不确定"
	c.cn["bAutoResetGuildNoOnlinePlayers"] = "自动重置没有在线玩家的公会，默认False即可"
	c.cn["AutoResetGuildTimeNoOnlinePlayers"] = "无在线玩家时自动重置生成时间，默认72即可"
	c.cn["GuildPlayerMaxNum"] = "公会成员最大数量，默认20即可"
	c.cn["PalEggDefaultHatchingTime"] = "帕鲁蛋默认孵化时间，72是小时，调成0即可没有孵化时间。0.1~72之间可以自己输入"
	c.cn["WorkSpeedRate"] = "工作速率，影响流水线物品生产速度，默认1，建议3"
	c.cn["bIsMultiplay"] = "多人游戏，默认false，如果是局域网创建服务器玩家不影响，False即可"
	c.cn["bIsPvP"] = "PVP是否开启"
	c.cn["bCanPickupOtherGuildDeathPenaltyDrop"] = "可拾取其他公会的死亡掉落物，默认False即可"
	c.cn["bEnableNonLoginPenalty"] = "启用不登录惩罚，，应该指代的是无人在线时是否会出现袭击事件，默认True应该也没影响，担心出问题的可以改False"
	c.cn["bEnableFastTravel"] = "启用快速旅行，默认True即可"
	c.cn["bIsStartLocationSelectByMap"] = "通过地图选择起始位置默认True即可，如果改为False则全部出生在初始台地"
	c.cn["bExistPlayerAfterLogout"] = "注销后玩家仍然存在，就是是否删注销玩家的档，跟朋友一起玩的默认False即可"
	c.cn["bEnableDefenseOtherGuildPlayer"] = "启用防御其他公会玩家功能，默认False即可"
	c.cn["CoopPlayerMaxNum"] = "邀请码服务器玩家最大人数"
	c.cn["ServerPlayerMaxNum"] = "服务器玩家最大人数"
	c.cn["ServerName"] = "服务器名称 "
	c.cn["ServerDescription"] = "服务器简介"
	c.cn["AdminPassword"] = "管理员密码"
	c.cn["ServerPassword"] = "服务器密码"
	c.cn["PublicPort"] = "服务器对外端口"
	c.cn["PublicIP"] = "服务器IP"
	c.cn["RCONEnabled"] = "启用 RCON"
	c.cn["RCONPort"] = "RCON端口"
	c.cn["Region"] = "地区"
	c.cn["bUseAuth"] = "使用授权"
	c.cn["BanListURL"] = "封禁玩家名单（需外网）"
}

func NewConfig() *Config {
	info := GetInfo()
	cfgs, _ := ini.Load(fmt.Sprintf("%s/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini", info.PalPath))
	config := &Config{
		value: NewOrderMap(),
		cn:    make(map[string]string),
		cfg:   cfgs,
	}
	config.initCN()
	config.Parse()
	return config
}

func (c *Config) Parse() {
	infos := c.cfg.Section("/Script/Pal.PalGameWorldSettings").Key("OptionSettings").Value()
	infos = infos[1 : len(infos)-1]
	kvs := strings.Split(infos, ",")
	for _, v := range kvs {
		vals := strings.Split(v, "=")
		c.value.Store(vals[0], vals[1])
	}
}

func (c *Config) ForEach(fn ConfigFunc) {
	c.value.ForEach(func(key, value any) bool {
		return fn(key, value)
	})
}

func (c *Config) Get(key string) any {
	return c.value.Load(key)
}

func (c *Config) Set(key string, val any) {
	c.value.Store(key, val)
}

func (c *Config) GetCN(key string) string {
	return c.cn[key]
}

func (c *Config) Len() int {
	return len(c.cn)
}

func (c *Config) Save() {
	str := "("
	c.value.ForEach(func(key, value any) bool {
		str += fmt.Sprintf("%s=%v,", key, value)
		return true
	})
	str = str[:len(str)-1]
	str += ")"
	c.cfg.Section("/Script/Pal.PalGameWorldSettings").Key("OptionSettings").SetValue(str)
	info := GetInfo()
	c.cfg.SaveTo(fmt.Sprintf("%s/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini", info.PalPath))
}
